home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / tipx / xfer / zmodem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-11  |  16.2 KB  |  909 lines

  1. /*+-------------------------------------------------------------------------
  2.     zmodem.c - ZMODEM protocol primitives
  3.     based on code by Chuck Forsberg
  4.     tip adaptation by wht%n4hgf@emory.mathcs.emory.edu
  5.  
  6.   Entry point Functions:
  7.     zsbhdr(type,hdr) send binary header
  8.     zshhdr(type,hdr) send hex header
  9.     zgethdr(hdr,eflag) receive header - binary or hex
  10.     zsdata(buf,len,frameend) send data
  11.     zrdata(buf,len) receive data
  12.     stohdr(pos) store position data in Txhdr
  13.     long rclhdr(hdr) recover position offset from header
  14.  
  15.   Defined functions:
  16.     noxrd7()
  17.     rclhdr(hdr)
  18.     stohdr(pos)
  19.     zdlread()
  20.     zgeth1()
  21.     zgethdr(hdr,eflag)
  22.     zgethex()
  23.     zputhex(c)
  24.     zrbhdr(hdr)
  25.     zrbhdr32(hdr)
  26.     zrdat32(buf,length)
  27.     zrdata(buf,length)
  28.     zrhhdr(hdr)
  29.     zsbh32(hdr,type)
  30.     zsbhdr(type,hdr)
  31.     zsda32(buf,length,frameend)
  32.     zsdata(buf,length,frameend)
  33.     zsendline(c)
  34.     zshhdr(type,hdr)
  35.  
  36. --------------------------------------------------------------------------*/
  37. /*+:EDITS:*/
  38. /*:08-23-1990-13:48-wht@tridom-add mode 4 code */
  39. /*:05-21-1990-16:00-wht@tridom-adapt ecu xfer protocols for tipwht */
  40.  
  41. #include "zmodem.h"            /* wht */
  42. #include "zlint.h"
  43.  
  44. extern char s128[];                /* wht */
  45. extern int Zctlesc;                /* wht */
  46. extern int Zmodem;                /* wht */
  47. extern long cr3tab[];            /* wht */
  48. extern unsigned Baudrate;        /* wht */
  49. extern unsigned short crctab[];    /* wht */
  50.  
  51. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  52.  
  53. #if !defined(UNSL)
  54. #define UNSL
  55. #endif
  56.  
  57.  
  58.  
  59. static lastsent;    /* Last char we sent */
  60. static evenp;        /* Even parity seen on header */
  61.  
  62. /* Globals used by ZMODEM functions */
  63. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  64. char Rxhdr[4];        /* Received header */
  65. char Txhdr[4];        /* Transmitted header */
  66. int Crc32;        /* Display flag indicating 32 bit CRC being received */
  67. int Crc32t;        /* Display flag indicating 32 bit CRC being sent */
  68. int Rxcount;        /* Count of data bytes received */
  69. int Rxframeind;        /* ZBIN ZBIN32,or ZHEX type of frame received */
  70. int Rxtimeout;    /* Tenths of seconds to wait for something */
  71. int Rxtype;        /* Type of header received */
  72. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  73. int Zrwindow;    /* RX window size (controls garbage count) */
  74. long Rxpos;    /* Received file position */
  75. long Txpos;    /* Transmitted file position */
  76.  
  77. char *frametypes[] = 
  78. {
  79.     "Carrier Lost",        /* -3 */
  80.     "TIMEOUT",            /* -2 */
  81.     "ERROR",            /* -1 */
  82. /* #define FTOFFSET 3 moved to zmodem.h */
  83.     "ZRQINIT",
  84.     "ZRINIT",
  85.     "ZSINIT",
  86.     "ZACK ",
  87.     "ZFILE",
  88.     "ZSKIP",
  89.     "ZNAK ",
  90.     "ZABORT",
  91.     "ZFIN ",
  92.     "ZRPOS",
  93.     "ZDATA",
  94.     "ZEOF ",
  95.     "ZFERR",
  96.     "ZCRC ",
  97.     "ZCHALLENGE",
  98.     "ZCOMPL",
  99.     "ZCAN ",
  100.     "ZFREECNT",
  101.     "ZCOMMAND",
  102.     "ZSTDERR",
  103.     "xxxxx"
  104. #define FRTYPES 22    /* Total number of frame types in this array */
  105.     /*  not including psuedo negative entries */
  106. };
  107.  
  108. static char masked[] = "8 bit transparent path required";
  109. static char badcrc[] = "Bad CRC";
  110.  
  111. /* Send ZMODEM binary header hdr of type type */
  112. zsbhdr(type,hdr)
  113. register unsigned char *hdr;
  114. {
  115.     register int n;
  116.     register unsigned crc;
  117.  
  118.     report_tx_ind(1);
  119.     sprintf(s128,"hdr %s %ld",frametypes[type+FTOFFSET],rclhdr(hdr));
  120.     report_last_txhdr(s128,0);
  121.  
  122.     xsendline(ZPAD); 
  123.     xsendline(ZDLE);
  124.  
  125.     if(Crc32t=Txfcs32)
  126.         zsbh32(hdr,type);
  127.     else 
  128.     {
  129.         xsendline(ZBIN); 
  130.         zsendline(type); 
  131.         crc = updcrc(type,0);
  132.  
  133.         for(n=4; --n >= 0; ++hdr)
  134.         {
  135.             zsendline(*hdr);
  136.             crc = updcrc(*hdr,crc);
  137.         }
  138.         crc = updcrc(0,updcrc(0,crc));
  139.         zsendline(crc>>8);
  140.         zsendline(crc);
  141.     }
  142.     if(type != ZDATA)
  143.         flushline();
  144.     mode(4);
  145.     report_tx_ind(0);
  146. }
  147.  
  148.  
  149. /* Send ZMODEM binary header hdr of type type */
  150. zsbh32(hdr,type)
  151. register char *hdr;
  152. {
  153.     register int n;
  154.     register UNSL long crc;
  155.  
  156.     report_tx_ind(1);
  157.     xsendline(ZBIN32);  
  158.     zsendline(type);
  159.     crc = 0xFFFFFFFFL; 
  160.     crc = UPDC32(type,crc);
  161.  
  162.     for(n=4; --n >= 0; ++hdr)
  163.     {
  164.         crc = UPDC32((0377 & *hdr),crc);
  165.         zsendline(*hdr);
  166.     }
  167.     crc = ~crc;
  168.     for(n=4; --n >= 0;)
  169.     {
  170.         zsendline((int)crc);
  171.         crc >>= 8;
  172.     }
  173.     mode(4);
  174.     report_tx_ind(0);
  175. }
  176.  
  177. /* Send ZMODEM HEX header hdr of type type */
  178. zshhdr(type,hdr)
  179. register unsigned char *hdr;
  180. {
  181.     register int n;
  182.     register unsigned short crc;
  183.  
  184.     report_tx_ind(1);
  185.  
  186.     sprintf(s128,"hdr %s %ld",frametypes[type+FTOFFSET],rclhdr(hdr));
  187.     report_last_txhdr(s128,0);
  188.     sendline(ZPAD); 
  189.     sendline(ZPAD); 
  190.     sendline(ZDLE); 
  191.     sendline(ZHEX);
  192.     zputhex(type);
  193.     Crc32t = 0;
  194.  
  195.     crc = updcrc(type,0);
  196.     for(n=4; --n >= 0; ++hdr)
  197.     {
  198.         zputhex(*hdr); 
  199.         crc = updcrc(*hdr,crc);
  200. /*        crc = updcrc((0377 & *hdr),crc);  original - wht */
  201.     }
  202.     crc = updcrc(0,updcrc(0,crc));
  203.     zputhex(crc>>8); 
  204.     zputhex(crc);
  205.  
  206.     /* Make it printable on remote machine */
  207.     sendline(015); 
  208.     sendline(012);
  209.     /*
  210.      * Uncork the remote in case a fake XOFF has stopped data flow
  211.      */
  212.     if(type != ZFIN && type != ZACK)
  213.         sendline(021);
  214.     flushline();
  215.     mode(4);
  216.     report_tx_ind(0);
  217. }
  218.  
  219. /*
  220.  * Send binary array buf of length length,with ending ZDLE sequence frameend
  221.  */
  222. static char *Zendnames[] = { "ZCRCE","ZCRCG","ZCRCQ","ZCRCW"};
  223.  
  224. zsdata(buf,length,frameend)
  225. register unsigned char *buf;
  226. {
  227.     register unsigned short crc;
  228.  
  229.     report_tx_ind(1);
  230.  
  231.     sprintf(s128,"data %s %d bytes",Zendnames[frameend-ZCRCE&3],length);
  232.     report_last_txhdr(s128,0);
  233.     if(Crc32t)
  234.         zsda32(buf,length,frameend);
  235.     else 
  236.     {
  237.         crc = 0;
  238.         for(;--length >= 0; ++buf)
  239.         {
  240.             zsendline(*buf); 
  241.             crc = updcrc(*buf,crc);
  242.         }
  243.         xsendline(ZDLE); 
  244.         xsendline(frameend);
  245.         crc = updcrc(frameend,crc);
  246.  
  247.         crc = updcrc(0,updcrc(0,crc));
  248.         zsendline(crc>>8); 
  249.         zsendline(crc);
  250.     }
  251.     if(frameend == ZCRCW)
  252.     {
  253.         xsendline(XON);  
  254.         flushline();
  255.     }
  256.     mode(4);
  257.     report_tx_ind(0);
  258.  
  259. }
  260.  
  261. zsda32(buf,length,frameend)
  262. register char *buf;
  263. {
  264.     register int c;
  265.     register UNSL long crc;
  266.  
  267.     report_tx_ind(1);
  268.  
  269.     crc = 0xFFFFFFFFL;
  270.     for(;--length >= 0; ++buf)
  271.     {
  272.         c = *buf & 0377;
  273.         if(c & 0140)
  274.             xsendline(lastsent = c);
  275.         else
  276.             zsendline(c);
  277.         crc = UPDC32(c,crc);
  278.     }
  279.     xsendline(ZDLE); 
  280.     xsendline(frameend);
  281.     crc = UPDC32(frameend,crc);
  282.  
  283.     crc = ~crc;
  284.     for(length=4; --length >= 0;)
  285.     {
  286.         zsendline((int)crc);  
  287.         crc >>= 8;
  288.     }
  289.     mode(4);
  290.     report_tx_ind(0);
  291. }
  292.  
  293. /*
  294.  * Receive array buf of max length with ending ZDLE sequence
  295.  *  and CRC.  Returns the ending character or error code.
  296.  *  NB: On errors may store length+1 bytes!
  297.  */
  298. zrdata(buf,length)
  299. register char *buf;
  300. {
  301.     register int c;
  302.     register unsigned short crc;
  303.     register char *end;
  304.     register int d;
  305.  
  306.     report_rx_ind(1);
  307.  
  308.     if(Rxframeind == ZBIN32)
  309.     {
  310.         report_rx_ind(0);
  311.         return(zrdat32(buf,length));
  312.     }
  313.  
  314.     crc = Rxcount = 0;  
  315.     end = buf + length;
  316.     while(buf <= end)
  317.     {
  318.         if((c = zdlread()) & ~0377)
  319.         {
  320. crcfoo:
  321.             switch(c)
  322.             {
  323.             case GOTCRCE:
  324.             case GOTCRCG:
  325.             case GOTCRCQ:
  326.             case GOTCRCW:
  327.                 crc = updcrc(((d=c)&0377),crc);
  328.                 if((c = zdlread()) & ~0377)
  329.                     goto crcfoo;
  330.                 crc = updcrc(c,crc);
  331.                 if((c = zdlread()) & ~0377)
  332.                     goto crcfoo;
  333.                 crc = updcrc(c,crc);
  334.                 if(crc & 0xFFFF)
  335.                 {
  336.                     report_str(badcrc,0);
  337.                     report_rx_ind(0);
  338.                     return(ERROR);
  339.                 }
  340.                 Rxcount = length - (end - buf);
  341.                 report_rxblklen(Rxcount);
  342.                 sprintf(s128,"data %s %d bytes",
  343.                     Zendnames[d-GOTCRCE&3],Rxcount);
  344.                 report_last_rxhdr(s128,0);
  345.                 report_rx_ind(0);
  346.                 return(d);
  347.             case GOTCAN:
  348.                 report_str("Sender Cancelled",1);
  349.                 report_rx_ind(0);
  350.                 return(ZCAN);
  351.             case TIMEOUT:
  352.                 report_str("TIMEOUT",1);
  353.                 report_rx_ind(0);
  354.                 return(c);
  355.             default:
  356.                 report_str("Bad data subpacket",1);
  357.                 report_rx_ind(0);
  358.                 return(c);
  359.             }
  360.         }
  361.         *buf++ = c;
  362.         crc = updcrc(c,crc);
  363.     }
  364.     report_str("Data subpacket too long",1);
  365.     report_rx_ind(0);
  366.     return(ERROR);
  367. }
  368.  
  369. zrdat32(buf,length)
  370. register char *buf;
  371. {
  372.     register int c;
  373.     register UNSL long crc;
  374.     register char *end;
  375.     register int d;
  376.  
  377.     report_rx_ind(1);
  378.     crc = 0xFFFFFFFFL;  
  379.     Rxcount = 0;  
  380.     end = buf + length;
  381.     while(buf <= end)
  382.     {
  383.         if((c = zdlread()) & ~0377)
  384.         {
  385. crcfoo:
  386.             switch(c)
  387.             {
  388.             case GOTCRCE:
  389.             case GOTCRCG:
  390.             case GOTCRCQ:
  391.             case GOTCRCW:
  392.                 d = c;  
  393.                 c &= 0377;
  394.                 crc = UPDC32(c,crc);
  395.                 if((c = zdlread()) & ~0377)
  396.                     goto crcfoo;
  397.                 crc = UPDC32(c,crc);
  398.                 if((c = zdlread()) & ~0377)
  399.                     goto crcfoo;
  400.                 crc = UPDC32(c,crc);
  401.                 if((c = zdlread()) & ~0377)
  402.                     goto crcfoo;
  403.                 crc = UPDC32(c,crc);
  404.                 if((c = zdlread()) & ~0377)
  405.                     goto crcfoo;
  406.                 crc = UPDC32(c,crc);
  407.                 if(crc != 0xDEBB20E3)
  408.                 {
  409.                     report_str(badcrc,0);
  410.                     report_rx_ind(0);
  411.                     return(ERROR);
  412.                 }
  413.                 Rxcount = length - (end - buf);
  414.                 report_rxblklen(Rxcount);
  415.                 sprintf(s128,"data %s %d bytes",
  416.                     Zendnames[d-GOTCRCE&3],Rxcount);
  417.                 report_last_rxhdr(s128,0);
  418.                 report_rx_ind(0);
  419.                 return(d);
  420.             case GOTCAN:
  421.                 report_str("Sender Canceled",1);
  422.                 report_rx_ind(0);
  423.                 return(ZCAN);
  424.             case TIMEOUT:
  425.                 report_str("TIMEOUT",1);
  426.                 report_rx_ind(0);
  427.                 return(c);
  428.             default:
  429.                 report_str("Bad data subpacket",1);
  430.                 report_rx_ind(0);
  431.                 return(c);
  432.             }
  433.         }
  434.         *buf++ = c;
  435.         crc = UPDC32(c,crc);
  436.     }
  437.     report_str("Data subpacket too long",1);
  438.     report_rx_ind(0);
  439.     return(ERROR);
  440. }
  441.  
  442.  
  443. /*
  444.  * Read a ZMODEM header to hdr,either binary or hex.
  445.  *  eflag controls local display of non zmodem characters:
  446.  *    0:  no display
  447.  *    1:  display printing characters only
  448.  *    2:  display all non ZMODEM characters
  449.  *  On success,set Zmodem to 1,set Rxpos and return type of header.
  450.  *   Otherwise return negative on error.
  451.  *   Return ERROR instantly if ZCRCW sequence,for fast error recovery.
  452.  */
  453. zgethdr(hdr,eflag)
  454. char *hdr;
  455. {
  456. register int c,n,cancount;
  457.  
  458.     report_rx_ind(1);
  459.     n = Zrwindow + Baudrate;    /* Max bytes before start of frame */
  460.     Rxframeind = Rxtype = 0;
  461.  
  462. startover:
  463.     cancount = 5;
  464. again:
  465.     /* Return immediate ERROR if ZCRCW sequence seen */
  466.     switch(c = readline(Rxtimeout))
  467.     {
  468.     case RCDO:
  469.     case TIMEOUT:
  470.         goto fifi;
  471.     case CAN:
  472. gotcan:
  473.         if(--cancount <= 0)
  474.         {
  475.             c = ZCAN; 
  476.             goto fifi;
  477.         }
  478.         switch(c = readline(1))
  479.         {
  480.         case TIMEOUT:
  481.             goto again;
  482.         case ZCRCW:
  483.             c = ERROR;
  484.             /* **** FALL THRU TO **** */
  485.         case RCDO:
  486.             goto fifi;
  487.         default:
  488.             break;
  489.         case CAN:
  490.             if(--cancount <= 0)
  491.             {
  492.                 c = ZCAN; 
  493.                 goto fifi;
  494.             }
  495.             goto again;
  496.         }
  497.         /* **** FALL THRU TO **** */
  498.     default:
  499. agn2:
  500.         if( --n == 0)
  501.         {
  502.             report_str("Garbage count exceeded",1);
  503.             report_last_rxhdr("Noise",0);
  504.             report_rx_ind(0);
  505.             return(ERROR);
  506.         }
  507.         goto startover;
  508.     case ZPAD|0200:        /* This is what we want. */
  509.     case ZPAD:        /* This is what we want. */
  510.         evenp = c & 0200;
  511.         break;
  512.     }
  513.     cancount = 5;
  514. splat:
  515.     switch(c = noxrd7())
  516.     {
  517.     case ZPAD:
  518.         goto splat;
  519.     case RCDO:
  520.     case TIMEOUT:
  521.         goto fifi;
  522.     default:
  523.         goto agn2;
  524.     case ZDLE:        /* This is what we want. */
  525.         break;
  526.     }
  527.  
  528.     switch(c = noxrd7())
  529.     {
  530.     case RCDO:
  531.     case TIMEOUT:
  532.         goto fifi;
  533.     case ZBIN:
  534.         Rxframeind = ZBIN;  
  535.         Crc32 = FALSE;
  536.         c =  zrbhdr(hdr);
  537.         break;
  538.     case ZBIN32:
  539.         Crc32 = Rxframeind = ZBIN32;
  540.         c =  zrbhdr32(hdr);
  541.         break;
  542.     case ZHEX:
  543.         Rxframeind = ZHEX;  
  544.         Crc32 = FALSE;
  545.         c =  zrhhdr(hdr);
  546.         break;
  547.     case CAN:
  548.         goto gotcan;
  549.     default:
  550.         goto agn2;
  551.     }
  552.     Rxpos = hdr[ZP3] & 0377;
  553.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  554.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  555.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  556. fifi:
  557.     switch(c)
  558.     {
  559.     case GOTCAN:
  560.         c = ZCAN;
  561.         /* **** FALL THRU TO **** */
  562.     case ZNAK:
  563.     case ZCAN:
  564.     case ERROR:
  565.     case TIMEOUT:
  566.     case RCDO:
  567.         sprintf(s128,"Got %s",frametypes[c+FTOFFSET]);
  568.         report_str(s128,1);
  569.         /* **** FALL THRU TO **** */
  570.     default:
  571.         if(c >= -3 && c <= FRTYPES)
  572.             sprintf(s128,"hdr %s %ld",frametypes[c+FTOFFSET],Rxpos);
  573.         else
  574.             sprintf(s128,"hdr 0x%02x? %ld",c,Rxpos);
  575.         report_last_rxhdr(s128,0);
  576.     }
  577.     report_rx_ind(0);
  578.     return(c);
  579. }
  580.  
  581. /* Receive a binary style header (type and position) */
  582. zrbhdr(hdr)
  583. register char *hdr;
  584. {
  585.     register int c,n;
  586.     register unsigned short crc;
  587.  
  588.     if((c = zdlread()) & ~0377)
  589.         return(c);
  590.     Rxtype = c;
  591.     crc = updcrc(c,0);
  592.  
  593.     for(n=4; --n >= 0; ++hdr)
  594.     {
  595.         if((c = zdlread()) & ~0377)
  596.             return(c);
  597.         crc = updcrc(c,crc);
  598.         *hdr = c;
  599.     }
  600.     if((c = zdlread()) & ~0377)
  601.         return(c);
  602.     crc = updcrc(c,crc);
  603.     if((c = zdlread()) & ~0377)
  604.         return(c);
  605.     crc = updcrc(c,crc);
  606.     if(crc & 0xFFFF)
  607.     {
  608.         if(evenp)
  609.             report_str(masked,1);
  610.         report_str(badcrc,0);
  611.         return(ERROR);
  612.     }
  613. #if defined(ZMODEM)
  614.     Protocol = ZMODEM;
  615. #endif
  616.     Zmodem = 1;
  617.     return(Rxtype);
  618. }
  619.  
  620. /* Receive a binary style header (type and position) with 32 bit FCS */
  621. zrbhdr32(hdr)
  622. register char *hdr;
  623. {
  624.     register int c,n;
  625.     register UNSL long crc;
  626.  
  627.     if((c = zdlread()) & ~0377)
  628.         return(c);
  629.     Rxtype = c;
  630.     crc = 0xFFFFFFFFL; 
  631.     crc = UPDC32(c,crc);
  632.  
  633.     for(n=4; --n >= 0; ++hdr)
  634.     {
  635.         if((c = zdlread()) & ~0377)
  636.             return(c);
  637.         crc = UPDC32(c,crc);
  638.         *hdr = c;
  639.     }
  640.     for(n=4; --n >= 0;)
  641.     {
  642.         if((c = zdlread()) & ~0377)
  643.             return(c);
  644.         crc = UPDC32(c,crc);
  645.     }
  646.     if(crc != 0xDEBB20E3)
  647.     {
  648.         if(evenp)
  649.             report_str(masked,1);
  650.         report_str(badcrc,0);
  651.         return(ERROR);
  652.     }
  653. #if defined(ZMODEM)
  654.     Protocol = ZMODEM;
  655. #endif
  656.     Zmodem = 1;
  657.     return(Rxtype);
  658. }
  659.  
  660.  
  661. /* Receive a hex style header (type and position) */
  662. zrhhdr(hdr)
  663. char *hdr;
  664. {
  665.     register int c;
  666.     register unsigned short crc;
  667.     register int n;
  668.  
  669.     if((c = zgethex()) < 0)
  670.         return(c);
  671.     Rxtype = c;
  672.     crc = updcrc(c,0);
  673.  
  674.     for(n=4; --n >= 0; ++hdr)
  675.     {
  676.         if((c = zgethex()) < 0)
  677.             return(c);
  678.         crc = updcrc(c,crc);
  679.         *hdr = c;
  680.     }
  681.     if((c = zgethex()) < 0)
  682.         return(c);
  683.     crc = updcrc(c,crc);
  684.     if((c = zgethex()) < 0)
  685.         return(c);
  686.     crc = updcrc(c,crc);
  687.     if(crc & 0xFFFF)
  688.     {
  689.         report_str(badcrc,0); 
  690.         return(ERROR);
  691.     }
  692.     if(readline(1) == '\r')    /* Throw away possible cr/lf */
  693.         readline(1);
  694. #if defined(ZMODEM)
  695.     Protocol = ZMODEM;
  696. #endif
  697.     Zmodem = 1; 
  698.     return(Rxtype);
  699. }
  700.  
  701. /* Send a byte as two hex digits */
  702. zputhex(c)
  703. register int c;
  704. {
  705.     static char digits[]    = "0123456789abcdef";
  706.  
  707.     sendline(digits[(c&0xF0)>>4]);
  708.     sendline(digits[(c)&0xF]);
  709. }
  710.  
  711. /*
  712.  * Send character c with ZMODEM escape sequence encoding.
  713.  *  Escape XON,XOFF. Escape CR following @ (Telenet net escape)
  714.  */
  715. zsendline(c)
  716. {
  717.  
  718.     /* Quick check for non control characters */
  719.     if(c & 0140)
  720.         xsendline(lastsent = c);
  721.     else 
  722.     {
  723.         switch(c &= 0377)
  724.         {
  725.         case ZDLE:
  726.             xsendline(ZDLE);
  727.             xsendline(lastsent = (c ^= 0100));
  728.             break;
  729.         case 015:
  730.         case 0215:
  731.             if(!Zctlesc && (lastsent & 0177) != '@')
  732.                 goto sendit;
  733.             /* **** FALL THRU TO **** */
  734.         case 020:
  735.         case 021:
  736.         case 023:
  737.         case 0220:
  738.         case 0221:
  739.         case 0223:
  740.             xsendline(ZDLE);
  741.             c ^= 0100;
  742. sendit:
  743.             xsendline(lastsent = c);
  744.             break;
  745.         default:
  746.             if(Zctlesc && ! (c & 0140))
  747.             {
  748.                 xsendline(ZDLE);
  749.                 c ^= 0100;
  750.             }
  751.             xsendline(lastsent = c);
  752.         }
  753.     }
  754. }
  755.  
  756. /* Decode two lower case hex digits into an 8 bit byte value */
  757. zgethex()
  758. {
  759.     register int c;
  760.  
  761.     c = zgeth1();
  762.     return(c);
  763. }
  764. zgeth1()
  765. {
  766.     register int c,n;
  767.  
  768.     if((c = noxrd7()) < 0)
  769.         return(c);
  770.     n = c - '0';
  771.     if(n > 9)
  772.         n -= ('a' - ':');
  773.     if(n & ~0xF)
  774.         return(ERROR);
  775.     if((c = noxrd7()) < 0)
  776.         return(c);
  777.     c -= '0';
  778.     if(c > 9)
  779.         c -= ('a' - ':');
  780.     if(c & ~0xF)
  781.         return(ERROR);
  782.     c += (n<<4);
  783.     return(c);
  784. }
  785.  
  786. /*
  787.  * Read a byte,checking for ZMODEM escape encoding
  788.  *  including CAN*5 which represents a quick abort
  789.  */
  790. zdlread()
  791. {
  792.     register int c;
  793.  
  794. again:
  795.     /* Quick check for non control characters */
  796.     if((c = readline(Rxtimeout)) & 0140)
  797.         return(c);
  798.     switch(c)
  799.     {
  800.     case ZDLE:
  801.         break;
  802.     case 023:
  803.     case 0223:
  804.     case 021:
  805.     case 0221:
  806.         goto again;
  807.     default:
  808.         if(Zctlesc && !(c & 0140))
  809.         {
  810.             goto again;
  811.         }
  812.         return(c);
  813.     }
  814. again2:
  815.     if((c = readline(Rxtimeout)) < 0)
  816.         return(c);
  817.     if(c == CAN && (c = readline(Rxtimeout)) < 0)
  818.         return(c);
  819.     if(c == CAN && (c = readline(Rxtimeout)) < 0)
  820.         return(c);
  821.     if(c == CAN && (c = readline(Rxtimeout)) < 0)
  822.         return(c);
  823.     switch(c)
  824.     {
  825.     case CAN:
  826.         return(GOTCAN);
  827.     case ZCRCE:
  828.     case ZCRCG:
  829.     case ZCRCQ:
  830.     case ZCRCW:
  831.         return(c | GOTOR);
  832.     case ZRUB0:
  833.         return(0177);
  834.     case ZRUB1:
  835.         return(0377);
  836.     case 023:
  837.     case 0223:
  838.     case 021:
  839.     case 0221:
  840.         goto again2;
  841.     default:
  842.         if(Zctlesc && ! (c & 0140))
  843.         {
  844.             goto again2;
  845.         }
  846.         if((c & 0140) ==  0100)
  847.             return(c ^ 0100);
  848.         break;
  849.     }
  850.     sprintf(s128,"Bad escape sequence %x",c);
  851.     report_str(s128,1);
  852.     return(ERROR);
  853. }
  854.  
  855. /*
  856.  * Read a character from the modem line with timeout.
  857.  *  Eat parity,XON and XOFF characters.
  858.  */
  859. noxrd7()
  860. {
  861.     register int c;
  862.  
  863.     for(;;)
  864.     {
  865.         if((c = readline(Rxtimeout)) < 0)
  866.             return(c);
  867.         switch(c &= 0177)
  868.         {
  869.         case XON:
  870.         case XOFF:
  871.             continue;
  872.         default:
  873.             if(Zctlesc && !(c & 0140))
  874.                 continue;
  875.         case '\r':
  876.         case '\n':
  877.         case ZDLE:
  878.             return(c);
  879.         }
  880.     }
  881. }
  882.  
  883. /* Store long integer pos in Txhdr */
  884. stohdr(pos)
  885. long pos;
  886. {
  887.     Txhdr[ZP0] = pos;
  888.     Txhdr[ZP1] = pos>>8;
  889.     Txhdr[ZP2] = pos>>16;
  890.     Txhdr[ZP3] = pos>>24;
  891. }
  892.  
  893. /* Recover a long integer from a header */
  894. long
  895. rclhdr(hdr)
  896. register char *hdr;
  897. {
  898.     register long l;
  899.  
  900.     l = (hdr[ZP3] & 0377);
  901.     l = (l << 8) | (hdr[ZP2] & 0377);
  902.     l = (l << 8) | (hdr[ZP1] & 0377);
  903.     l = (l << 8) | (hdr[ZP0] & 0377);
  904.     return(l);
  905. }
  906.  
  907. /* end of zmodem.c */
  908. /* vi: set tabstop=4 shiftwidth=4: */
  909.